﻿using System;
using System.Collections.Generic;
using System.DirectoryServices;
using System.Text;

namespace SyncUserAccount
{
    public class ADHelper
    {
        public static DirectoryEntry GetSAAEntry()
        {
            DirectoryEntry entry = null;
            try
            {
                //entry = new DirectoryEntry("LDAP://OU=IT,OU=Users,OU=SAA,OU=Client,DC=saa,DC=com", "admin", "Wbd1S#b!Ls#du8");
                entry = new DirectoryEntry("LDAP://192.168.0.236/OU=Users,OU=SAA,OU=Client,DC=saa,DC=com", "admin", "Wbd1S#b!Ls#du8");
            }
            catch (Exception ex)
            {
            }
            return entry;
        }

        public static DirectoryEntry GetDisableEntry()
        {
            DirectoryEntry entry = null;
            try
            {
                entry = new DirectoryEntry("LDAP://192.168.0.236/OU=Disable Users,DC=saa,DC=com", "admin", "Wbd1S#b!Ls#du8");
            }
            catch (Exception ex)
            {
            }
            return entry;
        }

        public static DirectoryEntry GetMCPEntry()
        {
            DirectoryEntry entry = null;
            try
            {
                entry = new DirectoryEntry("LDAP://192.168.9.56/OU=SAA,DC=amphenolmcp,DC=com", "administrator", "@mph3n0lsnbE2!");
            }
            catch (Exception ex)
            {
            }
            return entry;
        }

        public static DirectoryEntry GetMCPDisableEntry()
        {
            DirectoryEntry entry = null;
            try
            {
                entry = new DirectoryEntry("LDAP://192.168.9.56/OU=Disable Users,DC=amphenolmcp,DC=com", "administrator", "@mph3n0lsnbE2!");
            }
            catch (Exception ex)
            {
            }
            return entry;
        }
        /// <summary>
        /// 获得DirectoryEntry对象实例,以管理员登陆AD
        /// </summary>
        /// <returns></returns>
        public static DirectoryEntry GetDirectoryObject()
        {
            DirectoryEntry entry = null;
            try
            {
                //entry = new DirectoryEntry("LDAP://10.10.10.16", "Peter", " ab#CD%1234", AuthenticationTypes.Secure);
                //entry = new DirectoryEntry("LDAP://saa.com", "Justus.Xu", "winds@1985", AuthenticationTypes.Secure);
                entry = new DirectoryEntry("LDAP://OU=Client,DC=saa,DC=com", "admin", "Wbd1S#b!Ls#du8");

                //entry = new DirectoryEntry(" DAP://OU=SAA,DC=amphenolmcp,DC=com","","");

            }
            catch (Exception ex)
            {
            }
            return entry;
        }

        /// <summary>
        /// 根据用户公共名称取得用户的 对象
        /// </summary>
        /// <param name="commonName">用户公共名称</param>
        /// <returns>如果找到该用户则返回用户的对象,否则返回 null</returns>
        public static DirectoryEntry GetDirectoryEntry(string commonName)
        {
            DirectoryEntry de = GetDirectoryObject();
            DirectorySearcher deSearch = new DirectorySearcher(de);
            deSearch.Filter = "(&(&(objectCategory=person)(objectClass=user))(cn=" + commonName.Replace("\\", "") + "))";
            deSearch.SearchScope = SearchScope.Subtree;
            try
            {
                SearchResult result = deSearch.FindOne();
                de = new DirectoryEntry(result.Path);
                return de;
            }
            catch (Exception ex)
            {
                return null;
            }
        }

        /// <summary>
        /// 修改查询到的用户
        /// </summary>
        /// <param name="commonName">通用名（displayName,系统中显示的中文字）</param>
        /// <param name="account">帐户名（如Peter）</param>
        /// <param name="organizeName">组织单元名（资讯中心）</param>
        /// <param name="password">密码</param>
        public static string ChangeADAccount(string commonName, string account, string password)
        {
            //获取对应AD实体
            DirectoryEntry user = GetDirectoryEntry(commonName);
            try
            {
                ADHelper.SetProperty(user, " sAMAccountName ", account);
                user.Invoke("SetPassword", new object[] { password });
                user.CommitChanges();
            }
            catch (Exception e)
            {
                throw e;
            }
            return user.Path;
        }

        /// <summary>
        /// 设置指定的属性值
        /// </summary>
        /// <param name="de"></param>
        /// <param name="propertyName">属性名称?</param>
        /// <param name="propertyValue">属性值</param>
        public static void SetProperty(DirectoryEntry de, string propertyName, string propertyValue)
        {
            if (de.Properties.Contains(propertyName))
            {
                if (String.IsNullOrEmpty(propertyValue))
                {
                    de.Properties[propertyName].RemoveAt(0);
                }
                else
                {
                    de.Properties[propertyName][0] = propertyValue;
                }
            }
            else
            {
                if (!String.IsNullOrEmpty(propertyValue))
                {
                    de.Properties[propertyName].Add(propertyValue);
                }
            }
        }

        #region  依据类别用户名 查找目录项
        /// <summary>
        /// 查找目录项
        /// </summary>
        /// <param name="category">分类 users</param>
        /// <param name="name">用户名</param>
        /// <returns>目录项实体</returns>
        public static DirectoryEntry FindObject(string category, string name)
        {
            DirectoryEntry de = null;
            DirectorySearcher ds = null;
            DirectoryEntry userEntry = null;
            try
            {
                de = ADHelper.GetDirectoryObject();
                ds = new DirectorySearcher(de);
                string queryFilter = string.Format("(&(objectCategory=" + category + ")(sAMAccountName={0}))", name);
                ds.Filter = queryFilter;
                ds.Sort.PropertyName = "cn";
                SearchResult sr = ds.FindOne();
                if (sr != null)
                {
                    userEntry = sr.GetDirectoryEntry();
                }
                return userEntry;
            }
            catch (Exception ex)
            {
                return new DirectoryEntry();
            }
            finally
            {
                if (ds != null)
                {
                    ds.Dispose();
                }
                if (de != null)
                {
                    de.Dispose();
                }
            }
        }
        #endregion

        #region  依据类别用户名 查找目录项
        /// <summary>
        /// 查找目录项
        /// </summary>
        /// <param name="de">AD地址</param>
        /// <param name="category">分类 users</param>
        /// <param name="name">用户名</param>
        /// <returns>目录项实体</returns>
        public static DirectoryEntry FindObjectByJobNo(DirectoryEntry de, string category, string jobNo)
        {
            DirectorySearcher ds = null;
            DirectoryEntry userEntry = null;
            try
            {
                ds = new DirectorySearcher(de);
                string queryFilter = string.Format("(&(objectCategory=" + category + ")(physicalDeliveryOfficeName={0}))", jobNo);
                ds.Filter = queryFilter;
                ds.Sort.PropertyName = "cn";
                SearchResult sr = ds.FindOne();
                if (sr != null)
                {
                    userEntry = sr.GetDirectoryEntry();
                }
                return userEntry;
            }
            catch (Exception ex)
            {
                return new DirectoryEntry();
            }
            finally
            {
                if (ds != null)
                {
                    ds.Dispose();
                }
                if (de != null)
                {
                    de.Dispose();
                }
            }
        }
        #endregion

        #region  依据类别用户名 查找目录项
        /// <summary>
        /// 查找目录项
        /// </summary>
        /// <param name="de">AD地址</param>
        /// <param name="category">分类 users</param>
        /// <param name="name">用户名</param>
        /// <returns>目录项实体</returns>
        public static DirectoryEntry FindObjectByName(DirectoryEntry de, string category, string name)
        {
            DirectorySearcher ds = null;
            DirectoryEntry userEntry = null;
            try
            {
                ds = new DirectorySearcher(de);
                string queryFilter = string.Format("(&(objectCategory=" + category + ")(sAMAccountName={0}))", name);
                ds.Filter = queryFilter;
                ds.Sort.PropertyName = "cn";
                SearchResult sr = ds.FindOne();
                if (sr != null)
                {
                    userEntry = sr.GetDirectoryEntry();
                }
                return userEntry;
            }
            catch (Exception ex)
            {
                return new DirectoryEntry();
            }
            finally
            {
                if (ds != null)
                {
                    ds.Dispose();
                }
                if (de != null)
                {
                    de.Dispose();
                }
            }
        }
        #endregion

        #region 判断用户是否已经存在域中
        /// <summary>
        /// 判断用户是否已经存在域中
        /// </summary>
        /// <param name="userName">用户名</param>
        /// <returns></returns>
        public static DirectoryEntry ExitUser(string userName)
        {
            try
            {
                DirectoryEntry de = null;
                de = FindObject("user", userName);
                if (de == null)
                {
                    return new DirectoryEntry(); ;
                }
                else
                {
                    return de;
                }
            }
            catch (Exception ex)
            {
                return new DirectoryEntry();
            }
        }
        #endregion

        #region 判断域中是否存在组
        /// <summary>
        /// 判断域中是否存在组
        /// </summary>
        /// <param name="groupName">组名</param>
        /// <returns></returns>lan
        private DirectoryEntry ExitGroup(string groupName, string groupPath)
        {
            DirectoryEntry rootUser = null;
            DirectoryEntry group = null;
            DirectoryEntry test = null;


            string path = GetOrganizeNamePath(groupPath);
            rootUser = ADHelper.GetDirectoryObject();
            test = new DirectoryEntry("WinNT://annet-or2,computer");


            try
            {
                var a = test.Children.Add("Users", "user");
                group = rootUser.Children.Find(groupName, "group");
                group = rootUser.Children.Find("CN=" + groupName);
                if (group != null)
                {
                    return group;
                }
                return new DirectoryEntry();
            }
            catch (Exception ex)
            {
                return new DirectoryEntry();
            }
        }
        #endregion

        #region 判断域中是否存在组织单位
        /// <summary>
        /// 判断域中是否存在组织单位
        /// </summary>
        /// <param name="organizeName">组织单位名</param>
        /// <returns></returns>
        public bool ExitOU(string organizeName)
        {
            DirectoryEntry rootUser = null;
            DirectoryEntry ouFind = null;
            if (string.IsNullOrEmpty(organizeName))
            {
                return true;
            }
            else
            {
                //分解路径
                string[] allOu = organizeName.Split(new char[] { '/' });
                //获取直属部门
                string OUName = allOu[allOu.Length - 1].ToString();
                try
                {
                    string path = GetOrganizeNamePath(organizeName);
                    rootUser = ADHelper.GetDirectoryObject();
                    ouFind = rootUser.Parent.Children.Find("OU=" + OUName);
                    if (ouFind != null)
                    {
                        return true;
                    }
                    return false;
                }
                catch (Exception ex)
                {
                    return false;
                }
            }
        }
        #endregion

        #region 获取域用户信息
        /// <summary>
        /// 获取域用户信息
        /// </summary>
        /// <param name="path">目录</param>
        /// <param name="username">用户名</param>
        /// <returns></returns>
        public static DomainUser GetAdUserInfo(string userName)
        {
            DomainUser du = new DomainUser();
            DirectoryEntry de = FindObject("user", userName);
            if (de != null)
            {
                if (de.Properties["samAccountName"].Value != null)
                {
                    du.UserId = de.Properties["samAccountName"].Value.ToString();
                }
                if (de.Properties["displayName"].Value != null)
                {
                    du.UserName = de.Properties["displayName"].Value.ToString();
                }
                if (de.Properties["userPrincipalName"].Value != null)
                {
                    du.UserPrincipalName = de.Properties["userPrincipalName"].Value.ToString();
                }
                if (de.Properties["telephoneNumber"].Value != null)
                {
                    du.Telephone = de.Properties["telephoneNumber"].Value.ToString();
                }
                if (de.Properties["mail"].Value != null)
                {
                    du.Email = de.Properties["mail"].Value.ToString();
                }
                if (de.Properties["description"].Value != null)
                {
                    du.Description = de.Properties["description"].Value.ToString();
                }
                if (de.Properties["Department"].Value != null)
                {
                    du.Department = de.Properties["Department"].Value.ToString();
                }
            }
            return du;
        }
        #endregion

        #region 获取域用户信息
        /// <summary>
        /// 获取域用户信息
        /// </summary>
        /// <param name="path">目录</param>
        /// <param name="username">用户名</param>
        /// <returns></returns>
        public static DirectoryEntry GetUserEntry(DirectoryEntry entry, string userName)
        {
            DomainUser du = new DomainUser();
            DirectoryEntry de = FindObjectByName(entry, "user", userName);
            return de;
        }
        #endregion

        #region 获取域用户信息
        /// <summary>
        /// 获取域用户信息
        /// </summary>
        /// <param name="path">目录</param>
        /// <param name="username">用户名</param>
        /// <returns></returns>
        public static DirectoryEntry GetUserEntryByJobNo(DirectoryEntry entry, string jobNo)
        {
            DomainUser du = new DomainUser();
            DirectoryEntry de = FindObjectByJobNo(entry, "user", jobNo);
            return de;
        }
        #endregion

        #region 从域中按照用户名查找用户
        /// <summary>
        /// 从域中按照用户名查找用户
        /// </summary>
        /// <param name="path">路径</param>
        /// <param name="AdUser">管理员账户</param>
        /// <param name="AdPwd">管理员密码</param>
        /// <param name="username">用户名</param>
        /// <returns></returns>
        private DirectoryEntry GetUser(string path, string username)
        {

            DirectoryEntry deuser;
            try
            {
                DirectoryEntry de = ADHelper.GetDirectoryObject();
                DirectorySearcher deSearch = new DirectorySearcher(de);
                deSearch.Filter = "(&(objectClass=user)(cn=" + username + "))";
                deSearch.SearchScope = SearchScope.Subtree;
                SearchResult result = deSearch.FindOne();
                if (result != null)
                {
                    deuser = result.GetDirectoryEntry();
                    return deuser;
                }
                else
                {
                    return null;
                }
            }
            catch (Exception ex)
            {
                return null;
            }
        }
        #endregion

        #region 进入AD域查询
        /// <summary>
        /// 查寻用户信息
        /// </summary>
        /// <param name="userName">用户名</param>
        private List<string> AccsesADQuery(string userName)
        {
            //定义de进入AD架构
            DirectoryEntry de = ADHelper.GetDirectoryObject();
            //定义ds查找AD
            DirectorySearcher ds = new DirectorySearcher(de);
            string value = string.Empty;
            List<string> domainList = new List<string>();
            try
            {
                //3.定义查询
                ds.Filter = "(SAMAccountName=" + userName + ")";
                ds.PropertiesToLoad.Add("SAMAccountName");//account
                ds.PropertiesToLoad.Add("Name");//full name
                ds.PropertiesToLoad.Add("displayName");
                ds.PropertiesToLoad.Add("mail");
                ds.PropertiesToLoad.Add("sn");
                ds.PropertiesToLoad.Add("description");
                ds.PropertiesToLoad.Add("Department");
                ds.PropertiesToLoad.Add("userPrincipalName");//user logon name,xxx@bdxy.com
                ds.PropertiesToLoad.Add("physicalDeliveryOfficeName");
                ds.PropertiesToLoad.Add("telephoneNumber");
                //查找一个
                SearchResult sr = ds.FindOne();
                if (sr != null)
                {
                    //列出值
                    foreach (string key in sr.Properties.PropertyNames)
                    {
                        foreach (object obj in de.Properties[key])
                        {
                            value += key + " = " + obj + Environment.NewLine;
                            domainList.Add(value);
                        }
                    }
                    return domainList;
                }
                else
                {
                    return domainList;
                }
            }
            catch (Exception ex)
            {
                return domainList;
            }
            finally
            {
                if (ds != null)
                {
                    ds.Dispose();
                }
                if (de != null)
                {
                    de.Dispose();
                }
            }
        }
        #endregion

        private string _ldapIdentity = "LDAP://saa.com/";
        #region 获取组织名称路径
        /// <summary>
        /// 获取组织名称路径
        /// </summary>
        /// <param name="organizeUnit">组织</param>
        /// <returns></returns>
        public string GetOrganizeNamePath(string organizeUnit)
        {
            StringBuilder sb = new StringBuilder();
            sb.Append(_ldapIdentity);
            return sb.Append(SplitOrganizeNameToDN(organizeUnit)).ToString();
        }
        #endregion

        private string _suffixPath = "DC=saa.com,DC=COM";
        #region 分隔组织名称为标准AD的DN名称
        /// <summary>
        /// 分隔组织名称为标准AD的DN名称,各个组织级别以"/"或"/"分开。如"总部/物业公司/小区"，并且当前域为
        /// bdxy.com，则返回的AD的DN表示名为"OU=小区,OU=物业公司,OU=总部,DC=bdxy,DC=com"。
        /// </summary>
        /// <param name="organizeName">组织名称</param>
        /// <returns>返回一个级别</returns>
        public string SplitOrganizeNameToDN(string organizeName)
        {
            StringBuilder sb = new StringBuilder();

            if (organizeName.Equals("Users") || string.IsNullOrEmpty(organizeName))
            {
                sb.Append("CN=Users,").Append(_suffixPath);
                return sb.ToString();
            }
            else
            {
                if (organizeName != null && organizeName.Length > 0)
                {
                    string[] allOu = organizeName.Split(new char[] { '/' });
                    for (int i = allOu.Length - 1; i >= 0; i--)
                    {
                        string ou = allOu[i];
                        if (sb.Length > 0)
                        {
                            sb.Append(",");
                        }
                        sb.Append("OU=").Append(ou);
                    }
                }

                //如果传入了组织名称，则添加,
                if (sb.Length > 0)
                {
                    sb.Append(",");
                }
                sb.Append(_suffixPath);
                return sb.ToString();
            }
        }
        #endregion


        public static List<DomainUser> GetUsers(DirectoryEntry entry)
        {
            List<DomainUser> users = new List<DomainUser>();

            using (entry)
            {
                using (DirectorySearcher searcher = new DirectorySearcher(entry))
                {
                    searcher.SizeLimit = 5000;//  ConfigUtility.DirectorySearcherSizeLimit;

                    searcher.SearchScope = SearchScope.Subtree;
                    string searchFilter = string.Empty;

                    searchFilter = string.Format("(objectClass=user)");
                    searcher.Filter = searchFilter;

                    SearchResultCollection src = null;
                    try
                    {
                        src = searcher.FindAll();
                    }
                    catch (Exception ex)
                    {
                        return users;
                    }
                    foreach (SearchResult sr in src)
                    {
                        DomainUser du = new DomainUser();

                        if (sr.Properties.Contains("samAccountName"))
                        {
                            du.UserId = sr.Properties["samAccountName"][0].ToString();
                        }
                        if (sr.Properties.Contains("displayName"))
                        {
                            du.UserName = sr.Properties["displayName"][0].ToString();
                        }
                        if (sr.Properties.Contains("userPrincipalName"))
                        {
                            du.UserPrincipalName = sr.Properties["userPrincipalName"][0].ToString();
                        }
                        if (sr.Properties.Contains("telephoneNumber"))
                        {
                            du.Telephone = sr.Properties["telephoneNumber"][0].ToString();
                        }
                        if (sr.Properties.Contains("mail"))
                        {
                            du.Email = sr.Properties["mail"][0].ToString();
                        }
                        if (sr.Properties.Contains("description"))
                        {
                            du.Description = sr.Properties["description"][0].ToString();
                        }
                        if (sr.Properties.Contains("Department"))
                        {
                            du.Department = sr.Properties["Department"][0].ToString();
                        }

                        users.Add(du);
                    }
                }
            }

            return users;
        }
    }
}

